package com.example.aacwebdemo.oauth;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import okhttp3.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("oauth")
public class OAuthController {

    private double version = 0d;
    private List<Object> staticUserList = null;

    private Gson gson = new GsonBuilder()
            //序列化null
            .serializeNulls()
            // 设置日期时间格式，另有2个重载方法
            // 在序列化和反序化时均生效
            .setDateFormat("yyyy-MM-dd")
            // 禁此序列化内部类
            .disableInnerClassSerialization()
            //生成不可执行的Json（多了 )]}' 这4个字符）
            //.generateNonExecutableJson()
            //禁止转义html标签
            .disableHtmlEscaping()
            //格式化输出
            //.setPrettyPrinting()
            .create();

    private OkHttpClient client =new OkHttpClient.Builder()
            .connectTimeout(50L,TimeUnit.SECONDS)
                        .readTimeout(60L, TimeUnit.SECONDS)
            .sslSocketFactory(createSSLSocketFactory1(), new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }).hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            })
            .build();

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLContext sslContext = null;
        try {
            Resource resource = new ClassPathResource("https.crt");
            InputStream certificates = resource.getInputStream();

            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

            Certificate ca;
            try {
                ca = certificateFactory.generateCertificate(certificates);
            } finally {
                certificates.close();
            }

            // Create a KeyStore containing our trusted CAs
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            // Create a TrustManager that trusts the CAs in our KeyStore
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            // Create an SSLContext that uses our TrustManager
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return sslContext != null ? sslContext.getSocketFactory() : null;

    }

    private static SSLSocketFactory createSSLSocketFactory1() {
        SSLSocketFactory ssfFactory = null;

        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }}, new SecureRandom());

            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
        }

        return ssfFactory;

    }
    @RequestMapping(value="authorization",method = RequestMethod.POST)
    public Object authorization(@RequestBody Map<String,String> body){
        try{
            String code = body.get("code");
            String enterpriseID  = body.get("enterprise_id");
            String accessTokenStr = getAccessToken(enterpriseID);
            System.out.println(accessTokenStr);
            Map<String,Object> accessTokenMap = gson.fromJson(accessTokenStr, HashMap.class);
            String accessToken = accessTokenMap.get("access_token")+"";
            String userStr = getUserByOAuth2(code,accessToken);
            System.out.println(userStr);
            Map<String,Object> userMap = gson.fromJson(userStr, HashMap.class);
            userMap.put("access_token",accessToken);
            return userMap;
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value="userList",method = RequestMethod.POST)
    public Object getUserList(@RequestBody Map<String,String> body){
        try {
            String accessToken = body.get("access_token")+"";
            Object userList = getUserList(accessToken);
            return userList;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value="sendMessage",method = RequestMethod.POST)
    public Object sendMessage(@RequestBody Map<String,String> body){
        try {
            String accessToken = body.get("access_token")+"";
            String number = body.get("number")+"";
            snedMessage2Server(accessToken,number);
            return "ok";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getAccessToken(String enterpriseID) throws IOException {
        String url = "https://192.168.6.77:9008/api/apps/v1/access-tokens" +
                "?app_key=APPF8BF6C576D2C16B116EE5AD5" +
                "&corp_id=" + enterpriseID +
                "&corp_secret=5k8P8I4n8o0i2A18_TkKv53g6eIf3pScJ_P1c8I57gyymTqGJA_2sebFv5402w8MN92";
        Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        return response.body().string();
    }

    private String getUserByOAuth2(String oauthCode,String accessToken) throws IOException {
        String url = "https://192.168.6.77:9008/api/apps/v1/sso/user"
                + "?access_token=" + accessToken
                + "&oauth_code=" + oauthCode;
        Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        return response.body().string();
    }

    private Object getUserList(String accessToken) throws IOException {
        String url = " https://192.168.6.77:9008/api/apps/v1/address-book" +
                "?access_token=" + accessToken;

        Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        String userListStr = response.body().string();

        Map<String,Object> userList = gson.fromJson(userListStr,HashMap.class);

        version = (double)(userList.get("version"));

        Object u = userList.get("staffs");

        List<Object> ul =gson.fromJson(gson.toJson(u), ArrayList.class);
        staticUserList = ul;
        System.out.println(userListStr);
        return ul;
    }

    private void snedMessage2Server(String accessToken,String number) {
        try{
            String url = " https://192.168.6.77:9008/api/apps/v1/push" +
                    "?access_token=" + accessToken;

            Map<String,Object> requestMap = creatMap1(number);
//            Map<String,Object> requestMap = creatMap2(number);
//            Map<String,Object> requestMap = creatMap3(number);

            System.out.println(gson.toJson(requestMap));

            MediaType mediaType = MediaType.parse("application/json;charset=UTF-8");

            okhttp3.RequestBody requestBody = okhttp3.RequestBody
                    .create( gson.toJson(requestMap),mediaType);

            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            Call call = client.newCall(request);
            Response response = call.execute();
            String responseStr = response.body().string();

            //Map<String,Object> responseMap = gson.fromJson(responseStr,HashMap.class);
            System.out.println(responseStr);
        }catch(Exception e){
            e.printStackTrace();
        }


    }

    private Map<String,Object> creatMap1(String number){
        Map<String,Object> requestMap = new HashMap<>();
        requestMap.put("type","MOBILE");
        requestMap.put("recipients",new String[]{number});
        requestMap.put("badge_number",20);

        Map<String,Object> msgContentMap = new HashMap<>();
        msgContentMap.put("title","哼哼");
        msgContentMap.put("subject","哈哈");
        msgContentMap.put("content","叽叽");

        Map<String,Object> messageMap = new HashMap<>();
        messageMap.put("msgType","text");
        messageMap.put("msgContent",msgContentMap);

        requestMap.put("message",gson.toJson(messageMap));

        return requestMap;
    }

    private Map<String,Object> creatMap2(String number){
        Map<String,Object> requestMap = new HashMap<>();
        requestMap.put("type","MOBILE");
        requestMap.put("recipients",new String[]{number});
        requestMap.put("badge_number",20);

        Map<String,Object> msgContentMap = new HashMap<>();
        msgContentMap.put("title","哼哼");
        msgContentMap.put("subject","哈哈");
        msgContentMap.put("content","叽叽");


        List<Map<String,Object>> actionList = new ArrayList<>();
        Map<String,Object> action1 = new HashMap<>();
        action1.put("name","111");
        action1.put("action","action1");
        actionList.add(action1);

        Map<String,Object> action2 = new HashMap<>();
        action2.put("name","222");
        action2.put("action","action2");
        actionList.add(action2);

        msgContentMap.put("actions",actionList);


        Map<String,Object> messageMap = new HashMap<>();
        messageMap.put("msgType","link");
        messageMap.put("msgContent",msgContentMap);

        requestMap.put("message",gson.toJson(messageMap));

        return requestMap;
    }

    private Map<String,Object> creatMap3(String number){
        Map<String,Object> requestMap = new HashMap<>();
        requestMap.put("type","MOBILE");
        requestMap.put("recipients",new String[]{number});
        requestMap.put("badge_number",20);

        Map<String,Object> msgContentMap = new HashMap<>();
        msgContentMap.put("title","测试title");
        msgContentMap.put("subject","测试subject");
        msgContentMap.put("content","测试content");


        List<Map<String,Object>> actionList = new ArrayList<>();
        Map<String,Object> action1 = new HashMap<>();
        action1.put("name","name1");
        action1.put("action","action1");
        actionList.add(action1);

        Map<String,Object> action2 = new HashMap<>();
        action2.put("name","name1");
        action2.put("action","action2");
        actionList.add(action2);

        msgContentMap.put("actions",actionList);


        Map<String,Object> messageMap = new HashMap<>();
        messageMap.put("msgType","multi_link");
        messageMap.put("msgContent",msgContentMap);

        requestMap.put("message",gson.toJson(messageMap));

        return requestMap;
    }

    public static void main(String[] args) {
        OAuthController o = new OAuthController();
        o.snedMessage2Server("mevNJJbc2j68j7ESe1C9T85k65Xd57Sh_wD1cpR102O4G0FAzRetga0a6029T9Vr8_Q8Rx3c6GHYzA5yzuC4HZ3V8pewFr1Lu5_68OpfDr6eR3HHIePKfA0Stm165a4AKtF"
                ,"+8615510833196");
    }

}
